﻿/*****************************************************************//**
 * @file    FITKGraphObjectSketchGrid.h
 * @brief   Graph object for the sketch grid.
 * 
 * @sa      
 * FITKGraphObjectSketchPreview
 *  
 * @author  ChengHaotian (yeguangbaozi@foxmail.com)
 * @date    2024-12-05
 *********************************************************************/

#ifndef __FITKGRAPHOBJECTSKETCHGRID_H__
#define __FITKGRAPHOBJECTSKETCHGRID_H__

#include "FITKGraphObject3D.h"

#include "FITKVTKGraphAdaptorAPI.h"

#include "FITKGraphObjectSketchInteractivePreviewer.h"

#include <QVector3D>
#include <QList>

// Forward declaration
class vtkUnstructuredGrid;
class vtkPoints;
class vtkVector3d;
class vtkTextActor;

class FITKGraphActor;

namespace Exchange
{
    class FITKGraphObjectSketch2D;
}

namespace Interface
{
    class FITKGeoCommandList;
}

namespace Exchange
{
    /**
     * @brief   Graph object for the sketch grid.
     * @author  ChengHaotian (yeguangbaozi@foxmail.com)
     * @date    2024-12-05
     */
    class FITKVTKGRAPHADAPTORAPI FITKGraphObjectSketchGrid : public FITKGraphObject3D
    {
        // Regist
        FITKGraphObjectRegist(FITKGraphObjectSketchGrid, FITKGraphObject3D);
        FITKCLASS(Exchange, FITKGraphObjectSketchGrid);

        Q_OBJECT

    public:
        /**
         * @brief   Constructor.
         * @param   caseData: The case data
         * @param   cmdList: The geometry data object
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        FITKGraphObjectSketchGrid(AbaqusData::FITKDataCase* caseData, Interface::FITKGeoCommandList* cmdList);

        /**
         * @brief   Destructor.[virtual]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        virtual ~FITKGraphObjectSketchGrid();

        /**
         * @brief   Update the visibility with data object's visibility.[override]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        void updateVisibility() override;

        /**
         * @brief   Update all graph actors.[override]
         * @param   forceUpdate: Force update[default]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        void update(bool forceUpdate = false) override;

        /**
         * @brief   Get the data id.[override]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        int getDataId() override;

        /**
         * @brief   Get the visibility from the data object.[override]
         * @return  The visibility
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        bool getDataVisibility() override;

        /**
         * @brief   Show or hide graph object.[override]
         * @param   visibility: The visibility of graph object
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-11
         */
        void setVisible(bool visibility) override;

        /**
         * @brief   Get the fixed sized bounds of this graph object.[override]
         * @param   The bounds size
         * @return  If the graph object has fixed sized bounds
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-11
         */
        bool getFixedBounds(double* bounds) override;

        /**
         * @brief   Update the actor with the camera normal if necessary.[override]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        void updateCameraNormal() override;

        /**
         * @brief   Update the actor with the camera position if necessary.[override]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        void updateCameraPosition() override;

        /**
         * @brief   Update the actor with the mouse move if necessary.[override]
         * @param   pos: The display position of the mouse
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        void updateMouseMove(int* pos) override;

        /**
         * @brief   Update the actor with the mouse pressed if necessary.[override]
         * @param   pos: The display position of the mouse
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        void updateMousePressed(int* pos) override;

        /**
         * @brief   Get the echo position on the grid plane.
         * @param   pos: The position
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        void getEchoPosition(double* pos);

        /**
         * @brief   Start to draw the given shape by type.
         * @param   type: The shape type
         * @param   param: The additional parameter for modeling[default]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        void draw(SketchShapeType type, QVariant param = QVariant());

        /**
         * @brief   End the sketch modeling mode.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-09
         */
        void endSketch();

        /**
         * @brief   Get the valid pressed path positions of the sketch.
         * @return  The path positions of the sketch[const]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-09
         */
        const QVector<double> getSketchPathPositions();

        /**
         * @brief   Add a new sketch position manually.
         * @param   x: The horizontal position in sketch plane
         * @param   x: The verticle position in sketch plane
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-10
         */
        void addSketchPosition(double x, double y);

        /**
         * @brief   Remove the last sketch position.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-10
         */
        void removeLastSketcPosition();

        /**
         * @brief   Save the graph object for snipping.
         * @param   sketchGraphObj
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-16
         */
        void setCurrentSketchGraphObject(FITKGraphObject3D* sketchGraphObj);

    signals:
        /**
         * @brief   Signal - The signal for modeling finished.
         * @param   poses: The positions for modeling finished
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        void sig_modelingFinished(QVector<double> poses);

        /**
         * @brief   Signal - A new valid sketch path position had been added to the path position list.
         * @param   poses: All the pressed positions
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-09
         */
        void sig_validPressed(QVector<double> poses);

    private:
        /**
         * @brief   Initialize.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        void init();

        /**
         * @brief   Internal function - Initialize the grid cells with the given size.
         * @param   grid: The grid data
         * @param   size: The size of the grid 
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        void initGridCells(vtkUnstructuredGrid* grid, int size);

        /**
         * @brief   Internal function - Initialize the grid points with the given size.
         * @param   points: The grid points data
         * @param   size: The size of the grid
         * @param   globalSize: The size of the sketch
         * @param   up: The up direction of the plane
         * @param   right: The right direction of the plane
         * @param   bfPos: The bottom left position of the plane
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        void initGridPoints(vtkPoints* points, int size, double globalSize, vtkVector3d up, vtkVector3d right, double* bfPos);

        /**
         * @brief   Try to get the nearest point on the sub-grid lines with the given position.
         * @param   iPos: The given position
         * @param   oPos: The nearest grid point position
         * @param   oPxDist: The pixel distance from the mouse position to the snipped position on screen[quote]
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        void getNearestPositionOnGrid(double* iPos, double* oPos, double & oPxDist);

        /**
         * @brief   Try to get the nearest point on the saved sketch graph with the given position.
         * @param   iPos: The given position
         * @param   oPos: The nearest grid point position
         * @param   oPxDist: The pixel distance from the mouse position to the snipped position on screen[quote]
         * @return  Whether the position has a valid nearest position on current sketch
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-16
         */
        bool getNearestPositionOnSketch(double* iPos, double* oPos, double & oPxDist);

        /**
         * @brief   Generate the data set by the data object.
         * @return  Is OK
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        bool generateDataSet();

        /**
         * @brief   Generate the grid actors.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        void generateGraph();

        /**
         * @brief   Disable the light properties.
         * @param   fActor: The actor
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        void disableLightShadow(FITKGraphActor* fActor);

        /**
         * @brief   Update the cross dataset.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        void updateCross();

        /**
         * @brief   Get the cross scale factor.
         * @return  The factor
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        double getCrossScaleFactor();

        /**
         * @brief   Internal function - Get the nearest position to the given position.
         * @param   tarPos: The target position
         * @param   thePos: The given position need to calculate the distance
         * @param   nearestPos: The result posistion
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        void getTheNearestPos(double* tarPos, double* thePos, double* nearestPos);

    private:
        /**
         * @brief   The grid cell number of each direction.( Each quadrant has <m_numGrid * m_numGrid * 0.25> cells. )
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        int m_numGrid = 40;

        /**
         * @brief   The sub-grid cell of grid cell in each direction.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        int m_numSubGrid = 4;
        
        /**
         * @brief   The pixel size of the cross symbol.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        int m_crossPixelSize = 10;

        /**
         * @brief   While the distance from the eye to the grid center is smaller than this value,
         *          the sub grid lines will be shown.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        double m_ratioForSubGrid = 0.25;

        /**
         * @brief   The grid data for the main grid lines.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        vtkUnstructuredGrid* m_gridForMain{ nullptr };

        /**
         * @brief   The grid data for the sub grid lines.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        vtkUnstructuredGrid* m_gridForSub{ nullptr };

        /**
         * @brief   The grid data for the axis lines.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-11
         */
        vtkUnstructuredGrid* m_gridForAxis{ nullptr };

        /**
         * @brief   The grid data for the cross symbol.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        vtkUnstructuredGrid* m_gridForCross{ nullptr };

        /**
         * @brief   The grid points data for the main grid lines.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        vtkPoints* m_pointsForMain{ nullptr };

        /**
         * @brief   The grid points data for the sub grid lines.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        vtkPoints* m_pointsForSub{ nullptr };

        /**
         * @brief   The grid points data for axis lines.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-11
         */
        vtkPoints* m_pointsForAxis{ nullptr };

        /**
         * @brief   The grid points data for the cross symbol.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        vtkPoints* m_pointsForCross{ nullptr };

        /**
         * @brief   The actor for the main grid lines.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        FITKGraphActor* m_fActorGrid{ nullptr };

        /**
         * @brief   The actor for the sub grid lines.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        FITKGraphActor* m_fActorSubGrid{ nullptr };

        /**
         * @brief   The actor for the axis lines.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-11
         */
        FITKGraphActor* m_fActorAxis{ nullptr };

        /**
         * @brief   The actor for the cross symbol.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        FITKGraphActor* m_fActorCross{ nullptr };

        /**
         * @brief   The text actor for showing the position text.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-31
         */
        vtkTextActor* m_textActorPos{ nullptr };

        /**
         * @brief   The position of the sketch plane.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        double m_planePos[3]{ 0., 0., 0. };

        /**
         * @brief   The normal of the sketch plane.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        double m_planeNor[3]{ 0., 0., 0. };

        /**
         * @brief   The up direction of the sketch plane.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        double m_planeUp[3]{ 0., 0., 0. };

        /**
         * @brief   The right direction of the sketch plane.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        double m_planeRight[3]{ 0., 0., 0. };

        /**
         * @brief   The grid( sketch ) world size.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        double m_gridWorldSize = 200.;

        /**
         * @brief   The last position of the cross symbol.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-05
         */
        double m_crossPos[3]{ 0., 0., 0. };

        /**
         * @brief   The graph object for previewing the sketch interaction.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-06
         */
        FITKGraphObjectSketchInteractivePreviewer* m_sketchPreviewer{ nullptr };

        /**
         * @brief   Graph object for current sketch data.
         * @author  ChengHaotian (yeguangbaozi@foxmail.com)
         * @date    2024-12-16
         */
        FITKGraphObjectSketch2D* m_currentSketchGraphObj{ nullptr };

    };
}   // namespace Exchange

#endif // __FITKGRAPHOBJECTSKETCHGRID_H__
